JVM
内存区域(一)
1. 运行时内存区域分类
JVM
运行时内存区域主要包含:
- 程序计数器
- 栈
- 堆
- 方法区
其中属于线程私有的是程序计数器、栈;属于共享的是堆,方法区。2. 运行时内存区域含义
程序计数器
程序计数器是一块较小的内存空间,他可以当做当前线程执行的字节码的行号指示器。
栈
java
虚拟机栈和大多数程序语言一样,每个
java
方法在jvm
解释执行时都会创建一个栈帧存储局部变量、操作数栈、动态链接、方法出口信息。
每一个方法的调用到执行返回,都对应一个栈帧在虚拟机栈中入栈和出栈的过程。
局部变量表存放了编译时期确定的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用类型(reference类型)。其中long和double会占据两个局部变量槽(slot),其余的占据一个slot本地方法栈
本地方法调用形成的栈,类似于java虚拟机栈;
堆
所有的对象实例以及数组都要在堆上分配。
方法区
和堆内存一样,是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
运行时常量池(runtime constant pool)
运行时常量池是方法区的一部分。
Class
文件里面除了包含类版本、字段、方法、接口等描述信息外,还有一项就是常量表(符号表 constant pool table),用于存放编译时期(源码到字节码)产生的各种字面量和符号引用,例如public int a = 2
中的a
,这部分内容在类加载后会进入方法区的运行时常量池。
运行时常量池相对于class
文件的常量表的区别:- 常量表必须符合
class
文件严格的规范才会被虚拟机加载;而运行时常量池则是由不同的虚拟机厂商自由发挥实现的; - 运行时常量池具有动态性,常量并非只有在编译时期产生,也就是并非置入class文件中常量表的内容才能进入方法区中的运行时常量池,运行期间也可能有新的常量进入池中,这种特性就是常用的
string.inter()
方法。
- 常量表必须符合
直接内存(Direct Memory)
直接内存不是虚拟机运行时数据的一部分,
java
语言提供一些接口能够使用native
函数直接分配堆外内存(通常意义下虚拟机管理的内存以外的内存),参见NIO
。